home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-06-03 | 7.7 KB | 222 lines | [TEXT/EDIT] |
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; File: bignums-object.sch ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;
- (define make-bignum-object
- (lambda (internal-bignum . bases)
- (make-bignum-result-object
- (trampoline make-bignum
- (cons internal-bignum
- bases))
- (to-base?? bases))))
- ;
- (define make-bignum-result-object
- (lambda (user-bignum base)
- (let ((type 'soft-bignum)
- (the-remainder #f))
- (lambda (message . args)
- (cond ((eq? message 'get-base)
- base)
- ((eq? message 'change-base)
- (begin
- (if
- (or (bignum-zero? user-bignum)
- (bignum-=? user-bignum
- bignum-one))
- (set! base 'all)
- (begin
- (set! user-bignum
- (bignum-base-n->bignum-base-m
- user-bignum
- base
- (car args)))
- (set! base (car args))))
- base))
- ((eq? message 'change-sign)
- (begin
- (set! user-bignum
- (bignum-change-sign
- user-bignum))
- user-bignum))
- ((eq? message 'get-type)
- type)
- ((eq? message 'get-number)
- user-bignum)
- ((eq? message 'show-number)
- (show-bignum user-bignum))
- ((eq? message 'get-remainder)
- the-remainder)
- ((eq? message 'show-remainder)
- (show-bignum the-remainder))
- ((eq? message 'set-remainder)
- (set! the-remainder (car args)))
- ((eq? message '?)
- '(get-base change-base change-sign
- get-type get-number show-number
- get-remainder show-remainder
- set-remainder ?))
- (else
- (error "Bad message to bignum object."
- message)))))))
- ;
- (define copy-bignum-object
- (lambda (object)
- (let ((result (make-bignum-result-object
- (object 'get-number)
- (object 'get-base))))
- (begin
- (result 'set-remainder (object 'get-remainder))
- result))))
- ;
- ; Note: Friends and associates of bignum-=? are left
- ; to the reader to implement. They all will look quite
- ; similar to the below.
- ;
- (define bignum-=?
- (lambda (first second)
- (let ((first-sign (get-sign first))
- (second-sign (get-sign second)))
- (if (and (eq? first-sign second-sign)
- (big-=? (bignum-abs first)
- (bignum-abs second)))
- #t
- #f))))
- ;
- (define make-objects-base-compatible
- (lambda (object1 object2)
- (let ((object1-base (object1 'get-base))
- (object2-base (object2 'get-base)))
- (if (or (eq? object1-base 'all)
- (eq? object2-base 'all)
- (=? object1-base object2-base))
- (cons object1 object2)
- (if (>? object1-base
- object2-base)
- (cons object1
- (let ((second-object
- (copy-bignum-object
- object2)))
- (second-object 'change-base
- object1-base)
- second-object))
- (cons (let ((first-object
- (copy-bignum-object
- object1)))
- (first-object 'change-base
- object2-base)
- first-object)
- object2))))))
- ;
- (define find-common-base
- (lambda (object1 object2)
- (let ((object1-base (object1 'get-base))
- (object2-base (object2 'get-base)))
- (if (eq? object1-base 'all)
- (if (eq? object2-base 'all)
- 10
- object2-base)
- (if (eq? object2-base 'all)
- object1-base
- (if (>? object1-base object2-base)
- object1-base
- object2-base))))))
- ;
- (define bignum-object-div
- (lambda (dividend divisor)
- (let ((pair-of-objects (make-objects-base-compatible
- dividend divisor)))
- (let ((dividend (car pair-of-objects))
- (divisor (cdr pair-of-objects)))
- (let
- ((base (find-common-base dividend divisor)))
- (let
- ((result (bignum-div (dividend 'get-number)
- (divisor 'get-number)
- base)))
- (let ((the-quotient (first-digit result))
- (the-remainder (rest-digits result)))
- (let ((return-value
- (make-bignum-result-object
- the-quotient base)))
- (begin (return-value 'set-remainder
- the-remainder)
- return-value)))))))))
- ;
- (define bignum-object-mul
- (lambda (multiplicand multiplier)
- (let ((pair-of-objects
- (make-objects-base-compatible multiplicand
- multiplier)))
- (let ((multiplicand (car pair-of-objects))
- (multiplier (cdr pair-of-objects)))
- (let ((base (find-common-base multiplicand
- multiplier)))
- (let ((result (bignum-mul (multiplicand
- 'get-number)
- (multiplier
- 'get-number)
- base)))
- (make-bignum-result-object result
- base)))))))
- ;
- (define bignum-object-add
- (lambda (addend augend)
- (let ((pair-of-objects
- (make-objects-base-compatible addend
- augend)))
- (let ((addend (car pair-of-objects))
- (augend (cdr pair-of-objects)))
- (let ((base (find-common-base addend augend)))
- (let ((result (bignum-add
- (addend 'get-number)
- (augend 'get-number)
- base)))
- (make-bignum-result-object result
- base)))))))
- ;
- (define bignum-object-sub
- (lambda (minuend subtrahend)
- (let ((pair-of-objects (make-objects-base-compatible
- minuend subtrahend)))
- (let ((minuend (car pair-of-objects))
- (subtrahend (cdr pair-of-objects)))
- (let ((base (find-common-base minuend
- subtrahend)))
- (let ((result
- (bignum-sub (minuend 'get-number)
- (subtrahend 'get-number)
- base)))
- (make-bignum-result-object result
- base)))))))
- ;
- ; The below could be put into bignum object definition.
- ;
- (define bignum-object-base-n->bignum-object-base-m
- (lambda (bignum-object from-base to-base)
- (let ((result (bignum-base-n->bignum-base-m
- (bignum-object 'get-number)
- from-base
- to-base)))
- (make-bignum-result-object result to-base))))
- ;
- (define bignum-object-zero?
- (lambda (candidate)
- (bignum-zero? (candidate 'get-number))))
- ;
- (define bignum-object-zero
- (make-bignum-object ()))
- ;
- (define bignum-object-one
- (make-bignum-object '(1)))
- ;
- (define bignum-object-fact
- (lambda (n)
- (if (bignum-object-zero? n)
- bignum-object-one
- (bignum-object-mul
- n
- (bignum-object-fact
- (bignum-object-sub n
- bignum-object-one))))))
- ;
- 'done